package com.eliza.kotlin.design.creation.single

import com.eliza.ktor.all.library.utils.ToolsLog
import java.lang.reflect.Constructor


/*-*- coding:utf-8 -*-
 * @Author  : debi
 * @Time    : 6/4/22
 * @Software: IntelliJ IDEA
 */

/*
* 测试使用反射破坏单例模式
*/
class BreakSingletonReflect {

    private constructor() {
        synchronized(BreakSingletonReflect::class.java) {
            //判断flag的值是否是true，如果是true，说明非第一次访问，直接抛一个异常，如果是false的话，说明第一次访问
            if (flag) {
                ToolsLog.LogPrintln("flag:${flag} : 此乃第一次访问")
                /*
                    反射方式破解单例的解决方法
                * 这种方式比较好理解。当通过反射方式调用构造方法进行创建创建时
                * */
                throw RuntimeException("不能创建多个对象")
            }
            //将flag的值设置为true

            flag = true
        }
    }

    companion object {
        private var flag: Boolean = false

        private object SingletonHolder {
            val INSTANCE = BreakSingletonReflect()
        }

        fun getInstance() = SingletonHolder.INSTANCE

    }

}

fun main() {
    //1,获取Singleton的字节码对象

    val clazz: Class<BreakSingletonReflect> = BreakSingletonReflect::class.java

    //2,获取无参构造方法对象

//    val cons: Constructor<Singleton2> = clazz.getConstructor()
    val cons: Constructor<BreakSingletonReflect> = clazz.getDeclaredConstructor()
    //3,取消访问检查
    cons.isAccessible = true

    //4,创建Singleton对象

    val instance = cons.newInstance()
    val instance2 = cons.newInstance()

    ToolsLog.LogPrintln(instance == instance2, 13)
    ToolsLog.LogPrintln(" ${instance.hashCode()} \n ${instance2.hashCode()}", 13)
}